<script setup lang="ts">
import {onBeforeUpdate, onMounted, ref, watch} from "vue";
import StopBase from '@/assets/base/StopBase.dataurl?raw'
import start from '@/assets/base/start.dataurl?raw'
import right from '@/assets/base/right.dataurl?raw'
import left from '@/assets/base/left.dataurl?raw'
import stop from '@/assets/base/stop.dataurl?raw'
import BigStop from '@/assets/base/stopBig.dataurl?raw'
import sound from '@/assets/base/sound.dataurl?raw'
import hoverSound from '@/assets/base/hoverSound.dataurl?raw'
import BigStart from '@/assets/base/startBig.txt?raw'
import playing from '@/assets/base/playing.dataurl?raw'
import list from '@/assets/base/list.dataurl?raw'
import hoverList from '@/assets/base/hoverList.dataurl?raw'
import hoverRight from '@/assets/base/hoverRight.dataurl?raw'
import hoverLeft from '@/assets/base/hoverLeft.dataurl?raw'
import loop from '@/assets/base/loop.dataurl?raw'
import hoverLoop from '@/assets/base/hoverLoop.dataurl?raw'
import random from '@/assets/base/random.dataurl?raw'
import hoverRandom from '@/assets/base/hoverRandom.dataurl?raw'
import one from '@/assets/base/one.dataurl?raw'
import hoverOne from '@/assets/base/hoverOne.dataurl?raw'
import StartBase from '@/assets/base/StartBase.dataurl?raw'
import {MusicSrc} from './index.ts'

const props = defineProps({
    data: {
        type: Array<MusicSrc>,
        default: () => {
            return {
                src: '',
                song: '',
                singer: '',
                picture: '',
                time: ''
            }
        }
    }
})

enum LoopMode {
    LOOP = 0,
    RANDOM = 1,
    SINGLE = 2
}

const isPlay = ref(false)
const duration = ref('00:00')
const currentTime = ref('00:00')
const audio = ref<HTMLAudioElement | null>(null)
const soundVisible = ref(false)
const listVisible = ref(false)
const slider = ref(0)

const song = ref(props.data.length === 0 ? '' : props.data[0].song)
const singer = ref(props.data.length === 0 ? '' : props.data[0].singer)
const tableData = ref([])
const mode = ref<LoopMode>(LoopMode.LOOP)
const loopHover = ref(false)

onMounted(() => {
    // 构建tableData
    tableData.value = props.data.map(item => {
        return {
            src: item.src,
            song: item.song,
            singer: item.singer,
            time: item.time,
            picture: item.picture
        }
    })
    if (audio !== null) {
        if (props.data.length !== 0) {
            audio.value.src = props.data[0].src
            audio.value.onloadedmetadata = () => {
                const minter = Math.floor(audio.value!.duration / 60)
                const second = Math.floor(audio.value!.duration - minter * 60)
                duration.value = minter.toString().padStart(2, '0') + ":" + second.toString().padStart(2, '0')
            }
            slider.value = audio.value.volume * 100
        }
    }
    // 鼠标悬浮事件
    document.getElementsByClassName('img-start')[0].addEventListener('mouseover', () => {
        (document.getElementsByClassName('img-start')[0] as HTMLImageElement).src = isPlay.value ? BigStop : BigStart
    })
    // 鼠标离开事件
    document.getElementsByClassName('img-start')[0].addEventListener('mouseleave', () => {
        (document.getElementsByClassName('img-start')[0] as HTMLImageElement).src = isPlay.value ? stop : start
    })
    // 鼠标悬浮事件
    document.getElementById('music-list').addEventListener('mouseover', () => {
        (document.getElementById('music-list') as HTMLImageElement).src = hoverList
    })
    // 鼠标离开事件
    document.getElementById('music-list').addEventListener('mouseleave', () => {
        (document.getElementById('music-list') as HTMLImageElement).src = list
    })
    // 鼠标悬浮事件
    document.getElementById('music-sound').addEventListener('mouseover', () => {
        (document.getElementById('music-sound') as HTMLImageElement).src = hoverSound
    })
    // 鼠标离开事件
    document.getElementById('music-sound').addEventListener('mouseleave', () => {
        (document.getElementById('music-sound') as HTMLImageElement).src = sound
    })
    // 鼠标悬浮事件
    document.getElementById('music-left').addEventListener('mouseover', () => {
        (document.getElementById('music-left') as HTMLImageElement).src = hoverLeft
    })
    // 鼠标离开事件
    document.getElementById('music-left').addEventListener('mouseleave', () => {
        (document.getElementById('music-left') as HTMLImageElement).src = left
    })
    // 鼠标悬浮事件
    document.getElementById('music-right').addEventListener('mouseover', () => {
        (document.getElementById('music-right') as HTMLImageElement).src = hoverRight
    })
    // 鼠标离开事件
    document.getElementById('music-right').addEventListener('mouseleave', () => {
        (document.getElementById('music-right') as HTMLImageElement).src = right
    })
})

onBeforeUpdate(() => {
    tableData.value = props.data.map(item => {
        return {
            src: item.src,
            song: item.song,
            singer: item.singer,
            time: item.time,
            picture: item.picture
        }
    })
})

watch(slider, (val: number) => {
    if (audio !== null) {
        audio.value.volume = val / 100
    }
}, {deep: true})

const handleProcess = (val: any) => {
    audio.value.currentTime = (val.offsetX / (document.getElementsByClassName('process-box')[0].clientWidth as number)) * audio.value.duration;
    // 获取process-box的宽度
    const current = audio.value.currentTime;
    // 更新显示时间
    currentTime.value = formatTime(current);
    // 更新进度条
    const width = document.getElementsByClassName('process-box')[0].clientWidth as number
    (document.getElementsByClassName('process-inner')[0] as HTMLDivElement).style.width =
        (current / audio.value.duration * width) + 'px'
}

const handleStartPlayer = () => {
    if (isPlay.value) {
        audio.value.pause()
        const currentIndex = props.data.findIndex(item => item.src === audio.value.src);
        const overlay = document.getElementsByClassName('overlay')[currentIndex] as HTMLElement
        overlay.style.display = 'block'
        overlay.style.backgroundImage = `url(${StartBase})`
    } else {
        audio.value.load()
        audio.value.play()
        // 获取当前歌曲的索引
        const currentIndex = props.data.findIndex(item => item.src === audio.value.src);
        // 遍历全部的overlay，将不是当前索引的音乐更改overlay的backgroundImage
        for (let i = 0; i < props.data.length; i++) {
            if (i !== currentIndex) {
                const overlay = document.getElementsByClassName('overlay')[i] as HTMLElement
                overlay.style.display = 'none'
                overlay.style.backgroundImage = `url(${StopBase})`
            } else {
                const overlay = document.getElementsByClassName('overlay')[i] as HTMLElement
                overlay.style.display = 'block'
                overlay.style.backgroundImage = `url(${playing})`
            }
        }
        audio.value.ontimeupdate = () => {
            // 获取process-box的宽度
            const current = audio.value.currentTime;
            // 更新显示时间
            currentTime.value = formatTime(current);
            // 更新进度条
            const width = document.getElementsByClassName('process-box')[0].clientWidth as number
            (document.getElementsByClassName('process-inner')[0] as HTMLDivElement).style.width =
                (current / audio.value.duration * width) + 'px'
        }
        audio.value.onended = () => {
            if (mode.value === LoopMode.LOOP) {
                handleNextSong()
            } else if (mode.value === LoopMode.SINGLE) {
                audio.value.pause()
                audio.value.play()
            }
        }
    }
    isPlay.value = !isPlay.value
}

const formatTime = (seconds: number) => {
    const minutes = Math.floor(seconds / 60);
    const secs = Math.floor(seconds % 60);
    return `${String(minutes).padStart(2, '0')}:${String(secs).padStart(2, '0')}`;
}

const handleTablePlay = (val: any) => {
    if (audio === null) {
        return
    }
    audio.value.pause()
    isPlay.value = false
    audio.value.src = val.src
    song.value = val.song
    singer.value = val.singer
    handleStartPlayer()
}

const handleNextSong = () => {
    let nextIndex = 0
    if (mode.value === LoopMode.RANDOM) {
        nextIndex = Math.floor(Math.random() * tableData.value.length)
    }
    else {
        // 获取当前歌曲的索引
        const currentIndex = tableData.value.findIndex(item => item.song === song.value);
        // 计算下一首歌曲的索引
        nextIndex = currentIndex === tableData.value.length - 1 ? 0 : currentIndex + 1;
    }
    audio.value.pause()
    isPlay.value = false
    // 更新src、song和singer
    audio.value.src = tableData.value[nextIndex].src;
    song.value = tableData.value[nextIndex].song;
    singer.value = tableData.value[nextIndex].singer;
    // 播放下一首歌曲
    handleStartPlayer();
}

const handlePrevSong = () => {
    audio.value.pause()
    isPlay.value = false
    // 获取当前歌曲的索引
    const currentIndex = tableData.value.findIndex(item => item.song === song.value);
    // 计算上一首歌曲的索引
    const prevIndex = currentIndex === 0 ? tableData.value.length - 1 : currentIndex - 1;
    // 更新src、song和singer
    audio.value.src = tableData.value[prevIndex].src;
    song.value = tableData.value[prevIndex].song;
    singer.value = tableData.value[prevIndex].singer;
    // 播放上一首歌曲
    handleStartPlayer();
}

const handleLoopSong = () => {
    if (mode.value === LoopMode.LOOP) {
        mode.value = LoopMode.RANDOM
    } else if (mode.value === LoopMode.RANDOM) {
        mode.value = LoopMode.SINGLE
    } else if (mode.value === LoopMode.SINGLE) {
        mode.value = LoopMode.LOOP
    }
}

</script>

<template>
    <div style="height: 100px; ">
        <audio
            ref="audio"
            preload="metadata"
            controls
            style="display: none"
        />
        <el-row :gutter="5" style="width: 100%; margin-top: 15px; display: flex;
            justify-content: space-around; align-items: center;">
            <el-col :span="6">
                <div style="display: flex; ">
                    <el-avatar
                        style="cursor:pointer;"
                        src="https://d.musicapp.migu.cn/data/oss/resource/00/42/re/8e6902d1aaf04c6b9ef2a0fca112c64c.webp"
                        shape="square"
                        :size="60"/>
                    <div style="display: flex; flex-direction: column; justify-content: flex-start; margin-left: 5px">
                        <div>
                            <el-text tag="b" size="large">{{ song }}</el-text>
                        </div>
                        <div style="margin-top: auto">
                            <el-text tag="b" size="small" style="text-align: start">{{ singer }}</el-text>
                        </div>
                    </div>
                </div>
            </el-col>
            <el-col :span="12">
                <div style="width: 100%; display: flex; justify-content: center">
                    <div style="width: 300px; display: flex; justify-content: space-around; align-items: center">
                        <div style="width: 28px; height: 28px; cursor:pointer;">
                            <img :src="left" alt="left" style="width: 28px; height: 28px" id="music-left" @click="handlePrevSong">
                        </div>
                        <div style="width: 50px; height: 50px; cursor:pointer;" class="start-div" @click="handleStartPlayer">
                            <img :src="start" alt="start" class="img-start" v-if="!isPlay">
                            <img :src="stop" alt="stop" class="img-start" v-else>
                        </div>
                        <div style="width: 28px; height: 28px; cursor:pointer;">
                            <img :src="right" alt="right" style="width: 28px; height: 28px" id="music-right" @click="handleNextSong">
                        </div>
                        <div style="width: 28px; height: 28px; cursor:pointer;" v-if="mode === LoopMode.LOOP">
                            <img :src="loop" alt="right" style="width: 28px; height: 28px"
                                 @mouseover="loopHover = true"
                                 @mouseleave="loopHover = false"
                                 class="music-loop" v-if="!loopHover" @click="handleLoopSong">
                            <img :src="hoverLoop" alt="right" style="width: 28px; height: 28px"
                                 @mouseover="loopHover = true"
                                 @mouseleave="loopHover = false"
                                 class="music-loop" v-else @click="handleLoopSong">
                        </div>
                        <div style="width: 28px; height: 28px; cursor:pointer; " v-else-if="mode === LoopMode.RANDOM">
                            <img :src="random" alt="right" style="width: 28px; height: 28px"
                                 @mouseover="loopHover = true"
                                 @mouseleave="loopHover = false"
                                 class="music-loop" v-if="!loopHover" @click="handleLoopSong">
                            <img :src="hoverRandom" alt="right" style="width: 28px; height: 28px"
                                 @mouseover="loopHover = true"
                                 @mouseleave="loopHover = false"
                                 class="music-loop" v-else @click="handleLoopSong">
                        </div>
                        <div style="width: 28px; height: 28px; cursor:pointer; " v-else>
                            <img :src="one" alt="right" style="width: 28px; height: 28px"
                                 @mouseover="loopHover = true"
                                 @mouseleave="loopHover = false"
                                 class="music-loop" v-if="!loopHover" @click="handleLoopSong">
                            <img :src="hoverOne" alt="right" style="width: 28px; height: 28px"
                                 @mouseover="loopHover = true"
                                 @mouseleave="loopHover = false"
                                 class="music-loop" v-else @click="handleLoopSong">
                        </div>
                    </div>
                </div>
                <div style="width: 100%; display: flex; justify-content: space-around; align-items: center; margin-top: 5px;">
                    <el-text class="time-1">{{ currentTime }}</el-text>
                    <div class="process-box" @click="handleProcess">
                        <div class="process-inner">
                            <div class="process-dot"/>
                        </div>
                        <div class="process"/>
                    </div>
                    <el-text class="time-1">{{ duration }}</el-text>
                </div>
            </el-col>
            <el-col :span="6" style="display: flex; align-items: center; justify-content: flex-end">
                <el-popover
                    :visible="listVisible"
                    placement="top-start"
                    width="400"
                >
                    <div class="title">
                        <el-text tag="b" size="large">播放列表</el-text>
                        <el-divider style="background-color: #ff2667; margin: 5px 0"/>
                        <el-table height="45vh" :data="tableData" :border="false">
                            <el-table-column :label="'歌曲|' + data.length" prop="songInfo">
                                <template #default="scope">
                                    <div style="display: flex; ">
                                        <img style="border-radius: 3px;" :src="scope.row.picture" alt="" width="60" height="60">
                                        <div class="bg-layer" style="cursor:pointer;"/>
                                        <div class="overlay" @click="handleTablePlay(scope.row)"/>
                                        <div style="display: flex; flex-direction: column; justify-content: flex-start; margin-left: 5px">
                                            <div>
                                                <el-text truncated tag="b" size="large">{{ scope.row.song }}</el-text>
                                            </div>
                                            <div style="margin-top: auto">
                                                <el-text truncated tag="b" size="small" style="text-align: start">{{ scope.row.singer }}</el-text>
                                            </div>
                                        </div>
                                    </div>
                                </template>
                            </el-table-column>
                            <el-table-column label="时长" prop="time" width="100px"/>
                        </el-table>
                    </div>
                    <template #reference>
                        <div style="width: 28px; height: 28px; margin-right: 30px; cursor:pointer;" @click="listVisible = !listVisible">
                            <img :src="list" alt="music-list" style="width: 100%; height: 100%" id="music-list">
                        </div>
                    </template>
                </el-popover>

                <el-popover :visible="soundVisible" style="height: 180px" placement='top' width="60" popper-style="min-width: 10px;">
                    <el-space direction="vertical" class="sound-class">
                        <el-slider v-model="slider" vertical height="100px" :show-tooltip="false"/>
                        <el-divider style="margin: 3px auto"/>
                        <img :src="sound" alt="sound" style="width: 20px; height: 100%; margin-bottom: 5px"/>
                        <el-text size="small" style="text-align: center">
                            {{ slider }}%
                        </el-text>
                    </el-space>
                    <template #reference>
                        <div style="width: 28px; height: 28px; margin-right: 10px; cursor:pointer;" @click="soundVisible = !soundVisible">
                            <img :src="sound" alt="sound" style="width: 100%; height: 100%" id="music-sound">
                        </div>
                    </template>
                </el-popover>
            </el-col>
        </el-row>
    </div>
</template>

<style scoped lang="css">
.time-1 {
    color: #b3b8c5;
    font-size: .75rem;
    font-style: normal;
    font-weight: 400;
    line-height: normal;
}

.process-box {
    width: calc(100% - 90px);
    height: 2px;
    cursor: pointer;
}

.process {
    width: 100%;
    height: 2px;
    border-radius: 2px;
    background: #e7e9ee;
}

.process-inner {
    width: 0;
    height: 2px;
    position: absolute;
    border-radius: 2px;
    background: #ff2667;
}

.process-dot {
    width: 8px;
    height: 8px;
    border-radius: 8px;
    position: absolute;
    right: -4px;
    top: 1px;
    background: #ff2667;
    display: none;
    transform: translateY(-50%);
}

.process-box:hover .process-dot {
    display: block;
}

.img-start {
    width: 48px;
    height: 48px;
    transition: width 0.1s, height 0.1s;
}

.sound-class {
    text-align: center;
    align-items: center;
}

.overlay {
    display: none;
    opacity: .8;
    position: absolute;
    width: 30px;
    height: 30px;
    transform: translate(50%) translateY(50%);
    background-size: 100%;
    background-position: center;
    background-repeat: no-repeat;
    background-image: url();
    filter: drop-shadow(0px 0px 1px rgba(0, 0, 0, .25));
    cursor: pointer;
}

.bg-layer {
    width: 60px;
    height: 60px;
    position: absolute;
}


:deep(.el-table__row:hover .bg-layer) {
    background-color: #0003;
}

:deep(.el-table__row:hover .overlay) {
    display: block !important;
}

:deep(.el-slider__button) {
    width: 7px;
    height: 7px;
    border: none !important;
    position: absolute;
    right: 16px;
    bottom: 16px;
    background-color: #ff2667;
}

:deep(.el-slider__bar) {
    width: 2px !important;
    background-color: #ff2667;
}

:deep(.el-slider__runway) {
    width: 2px !important;
}

:deep(.el-table__cell) {
    color: #696f80;
    font-size: 12px;
    font-style: normal;
    font-weight: 500;
    line-height: normal;
    padding: 3px 0;
}

</style>
